#include "jxos_public.h"
#include "lib/bit.h"
#include <srtnet_config.h>
#include "../../../communication_layer/transmitter.h"
#include "../../application_layer_service.h"
#include "../../application_layer_binding_table.h"
#include "../../service_define.h"
#include "../../service_cmd_handler.h"

/************************************
	param[0] = need_bind_service_serila_mun;
	param[1] = need_bind_service_serila_id;
	param[2] = addr h byte;
	param[3] = addr l byte;
************************************/

#if (SRTNET_COMM_DEVICE_TYPE == SRTNET_COMM_DEVICE_TYPE_TRANSMITTER)\
    ||(SRTNET_COMM_DEVICE_TYPE == SRTNET_COMM_DEVICE_TYPE_REPEATER)
void srtnet_app_layer_service_id_binding_send_cmd_bind(uint8_t need_bind_service_serila_mun)
{
	uint8_t param[4];
	uint16_t addr;
	if(need_bind_service_serila_mun >= SERVICE_CONFIG_TABLE_LEN){
		sys_debug_print_task_user_print_str("need_bind_service_serila_mun out of range\r\n");
		return;
	}
	if(service_config_table[need_bind_service_serila_mun][SERVICE_CONFIG_TABLE_SERVICE_M_S_OBJECT] != SERVICE_MASTER){
		sys_debug_print_task_user_print_str("need_bind_service_serila_mun is not a master svr\r\n");
		return;
	}
#if (SRTNET_APP_LAYER_DEBUG_PRINT_ENABLE == 1)
	sys_debug_print_task_user_print_str("srtapp binding bind\r\n");
#endif
	param[0] = need_bind_service_serila_mun;
	param[1] = service_config_table[need_bind_service_serila_mun][SERVICE_CONFIG_TABLE_SERVICE_ID_OBJECT];
	addr = srtnet_comm_layer_transmitter_device_request_local_addr_read();
	param[2] = (addr>>8);
	param[3] = addr&0x00ff;
    srtnet_app_layer_service_master_send_cmd(true, DEFAULT_SERVICE_BUNDING_SERILA_NUM,
									SERVICE_BUNDING_ID,
									SERVICE_BUNDING_CMD_BUND,
									param, 4);
}

void srtnet_app_layer_service_id_binding_send_cmd_unbind(uint8_t need_bind_service_serila_mun)
{
	uint8_t param[4];
	uint16_t addr;
	if(service_config_table[need_bind_service_serila_mun][SERVICE_CONFIG_TABLE_SERVICE_M_S_OBJECT] != SERVICE_MASTER){
		return;
	}
#if (SRTNET_APP_LAYER_DEBUG_PRINT_ENABLE == 1)
	sys_debug_print_task_user_print_str("srtapp binding unbind\r\n");
#endif
	param[0] = need_bind_service_serila_mun;
	param[1] = service_config_table[need_bind_service_serila_mun][SERVICE_CONFIG_TABLE_SERVICE_ID_OBJECT];
	addr = srtnet_comm_layer_transmitter_device_request_local_addr_read();
	param[2] = (addr>>8);
	param[3] = addr&0x00ff;
    srtnet_app_layer_service_master_send_cmd(true, DEFAULT_SERVICE_BUNDING_SERILA_NUM,
									SERVICE_BUNDING_ID,
									SERVICE_BUNDING_CMD_UNBUND,
									param, 4);
}
#endif

#if (SRTNET_COMM_DEVICE_TYPE == SRTNET_COMM_DEVICE_TYPE_RECEIVER)\
    ||(SRTNET_COMM_DEVICE_TYPE == SRTNET_COMM_DEVICE_TYPE_REPEATER)
typedef struct {
	uint16_t master_addr;
	uint8_t master_service_serila_mun;
	uint8_t master_service_id;
	uint8_t slave_service_serila_mun;
} SRTNET_BINDING_STRUCT;
void (*srtnet_app_layer_service_id_binding_rec_cmd_bind_callback)(SRTNET_BINDING_STRUCT* param) = 0;
void (*srtnet_app_layer_service_id_binding_rec_cmd_unbind_callback)(SRTNET_BINDING_STRUCT* param) = 0;
void service_binding_rec_cmd_bind_handler(uint8_t* param)
{
	SRTNET_BINDING_STRUCT bind_s;
	uint8_t in_binding_table_service_serila_mun;
	uint16_t active_service_mark;
	bind_s.master_addr =  param[2];
	bind_s.master_addr <<= 8;
	bind_s.master_addr |= param[3];
	bind_s.master_service_serila_mun = param[0];
	bind_s.master_service_id = param[1];

	active_service_mark =  srtnet_app_layer_service_get_active_service_mark();

	for(in_binding_table_service_serila_mun = 0; in_binding_table_service_serila_mun < 16; in_binding_table_service_serila_mun++){
		if(get_bit_32(active_service_mark, in_binding_table_service_serila_mun) == 0){
			continue;
		}

		bind_s.slave_service_serila_mun = in_binding_table_service_serila_mun;
#if (SRTNET_APP_LAYER_DEBUG_PRINT_ENABLE == 1)
		sys_debug_print_task_user_print_str("srtapp binding rec bind\r\n");
		sys_debug_print_task_user_print_str("addr:");
		sys_debug_print_task_user_print_hex(bind_s.master_addr);
		sys_debug_print_task_user_print_str(" serila_mun:");
		sys_debug_print_task_user_print_uint(bind_s.master_service_serila_mun);
		sys_debug_print_task_user_print_str(" service_id:");
		sys_debug_print_task_user_print_uint(bind_s.master_service_id);
		sys_debug_print_task_user_print_str(" ---> binding to serila_mun:");
		sys_debug_print_task_user_print_uint(bind_s.slave_service_serila_mun);
		sys_debug_print_task_user_print_str("\r\n");
#endif
		if(bind_s.slave_service_serila_mun >= SERVICE_CONFIG_TABLE_LEN){
			return;
		}
		
		srtnet_app_layer_binding_table_lookup_reset();
		while(1){
			if(1 == srtnet_app_layer_binding_table_lookup(bind_s.master_addr,
													bind_s.master_service_serila_mun,
													bind_s.master_service_id,
													&in_binding_table_service_serila_mun)){
				if(in_binding_table_service_serila_mun == bind_s.slave_service_serila_mun){
					//already binded
					break;
				}
				else{
					continue;
				}
			}
			else{	//srtnet_app_layer_binding_table_lookup == 0, binding_table ergodic finish, not find bind log
				if(1 == srtnet_app_layer_binding_table_add(bind_s.master_addr,
														bind_s.master_service_serila_mun,
														bind_s.master_service_id,
														bind_s.slave_service_serila_mun)){
					sys_debug_print_task_user_print_str("success\r\n");
					if(srtnet_app_layer_service_id_binding_rec_cmd_bind_callback != 0){
						srtnet_app_layer_service_id_binding_rec_cmd_bind_callback(&bind_s);
					}
				}
				break;
			}
		}
	}
}

void service_binding_rec_cmd_unbind_handler(uint8_t* param)
{
	SRTNET_BINDING_STRUCT bind_s;

	bind_s.master_addr =  param[2];
	bind_s.master_addr <<= 8;
	bind_s.master_addr |= param[3];
	bind_s.master_service_serila_mun = param[0];
	bind_s.master_service_id = param[1];

	srtnet_app_layer_binding_table_lookup_reset();
	while(1){
		if(1 == srtnet_app_layer_binding_table_lookup(bind_s.master_addr,
												bind_s.master_service_serila_mun,
												bind_s.master_service_id,
												&(bind_s.slave_service_serila_mun))){
			if(bind_s.slave_service_serila_mun < SERVICE_CONFIG_TABLE_LEN){
				if(1 == srtnet_app_layer_binding_table_del(bind_s.master_addr,
												bind_s.master_service_serila_mun,
												bind_s.master_service_id,
												bind_s.slave_service_serila_mun)){
					if(srtnet_app_layer_service_id_binding_rec_cmd_unbind_callback != 0){
						srtnet_app_layer_service_id_binding_rec_cmd_unbind_callback(&bind_s);
					}
				}
			}
		}
		else{
			break;
		}
	}
}
#endif
